import Layout from '@/layout/index'
import ParentView from '@/layout/components/ParentView'
import InnerLink from '@/layout/components/InnerLink'
import { upperFirst, camelCase } from '@/utils/tools/string'
import { handleTree } from '@/utils/tools/transform'

const modules = import.meta.glob('./../views/**/*.vue')

const menuConst = {
  TYPE_MENU: 'C', // 菜单类型(菜单)
  TYPE_DIR: 'M', // 菜单类型(目录)
  LAYOUT: 'Layout',
  PARENT_VIEW: 'ParentView',
  INNER_LINK: 'InnerLink'
}

// 处理后台返回的菜单列表成树形
export function buildMenus(menus, isLoop = false) {
  const routers = []
  let menuTreeList = menus
  if (!isLoop) menuTreeList = handleTree(menus)
  menuTreeList.map(menu => {
    menu = formatterMenuKey(menu)
    let router = getRouter()
    router.hidden = menu.isVisible !== '1'
    router.name = getRouteName(menu)
    router.path = getRouterPath(menu)
    router.component = getComponent(menu)
    router.query = menu.query
    router.meta = getMeta(menu)
    const cMenus = menu.children || []
    if (cMenus && cMenus.length && menu.type === menuConst.TYPE_DIR) {
      router.alwaysShow = true
      router.redirect = 'noRedirect'
      router.children = buildMenus(cMenus, true)
    }
    if (cMenus && cMenus.length && menu.type === menuConst.TYPE_MENU) {
      // 菜单下 还有不展示的菜单菜单页面时，需要早dynamic中自定义动态路由，然后定义一个F类型权限控制
    } else if (isMenuFrame(menu)) {
      router.meta = null
      let children = getRouter()
      children.path = menu.url
      children.component = menu.component
      children.name = formatterName(menu.url)
      children.meta = getMeta(menu)
      children.query = menu.query
      router.children = [children]
    } else if (menu.parentId === 0 && isInnerLink(menu)) {
      router.path = '/'
      router.meta = getMeta(menu, { noCache: false, link: '' })
      let children = getRouter()
      const routerPath = innerLinkReplaceEach(menu.url)
      children.path = routerPath
      children.component = menuConst.INNER_LINK
      children.name = formatterName(routerPath)
      children.meta = getMeta(menu, { noCache: false })
      router.children = [children]
    }
    routers.push(router)
  })

  return routers
}

// 遍历后台传来的路由字符串，转换为组件对象
export function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
  return asyncRouterMap.filter(route => {
    if (type && route.children) {
      route.children = filterChildren(route.children)
    }
    if (route.component) {
      // Layout ParentView 组件特殊处理
      if (route.component === 'Layout') {
        route.component = Layout
      } else if (route.component === 'ParentView') {
        route.component = ParentView
      } else if (route.component === 'InnerLink') {
        route.component = InnerLink
      } else {
        route.component = loadView(route.component)
      }
    }
    if (route.children != null && route.children && route.children.length) {
      route.children = filterAsyncRouter(route.children, route, type)
    } else {
      delete route['children']
      delete route['redirect']
    }
    return true
  })
}

// 下划线转驼峰, 其实转不转都可以，纯粹个人
// 由于is_cache 在webstorm中有非合法单词提示，所以给转换成驼峰
function formatterMenuKey(menu) {
  let row = {}
  for (const key in menu) {
    if (Object.hasOwnProperty.call(menu, key)) {
      row[camelCase(key)] = menu[key]
    }
  }
  return row
}

// 将路由名的下滑和破这转大驼峰，
function formatterName(name) {
  return upperFirst(camelCase(name))
}
//获取路由名称
function getRouteName(menu) {
  let routerName = formatterName(menu.url)
  if (isMenuFrame(menu)) routerName = ''
  return routerName
}

//获取路由地址
function getRouterPath(menu) {
  let routerPath = menu.url
  // 内链打开外网方式
  if (menu.parentId !== 0 && isInnerLink(menu)) {
    routerPath = innerLinkReplaceEach(routerPath)
  } else if (isDirFrame(menu)) {
    routerPath = '/' + menu.url
  } else if (isMenuFrame(menu)) {
    routerPath = '/'
  }
  return routerPath
}

// 获取组件信息
function getComponent(menu) {
  let component = menuConst.LAYOUT
  if (menu.component && !isMenuFrame(menu)) {
    component = menu.component
  } else if (!menu.component && menu.parentId !== 0 && isInnerLink(menu)) {
    component = menuConst.INNER_LINK
  } else if (!menu.component && isParentView(menu)) {
    component = menuConst.PARENT_VIEW
  }
  return component
}

// 生成路由meta
function getMeta(menu, reset = {}) {
  let info = { title: menu.name, icon: menu.icon, noCache: menu.isCache === '0', link: menu.url }
  info = { ...info, ...reset }
  info.link = isHttp(info.link) ? info.link : ''
  return info
}

// 生成默认路由信息
function getRouter() {
  return {
    name: '',
    path: '',
    hidden: false,
    redirect: '',
    component: '',
    query: '',
    alwaysShow: false,
    meta: undefined,
    children: undefined
  }
}

// 是否为菜单内部跳转，一级菜单类型的非外链
// 一级菜单最终会转换成 一个子路由的模式，所以符合该方法的
function isMenuFrame(menu) {
  return menu.parentId === 0 && menu.type === menuConst.TYPE_MENU && menu.isExternal === '0'
}

// 是否是一级目录类型非外链
function isDirFrame(menu) {
  return menu.parentId === 0 && menu.type === menuConst.TYPE_DIR && menu.isExternal === '0'
}

// 是否为内链组件
function isInnerLink(menu) {
  return menu.isExternal === '0' && isHttp(menu.url)
}

// 是否为parent_view组件，非一级的目录类型
function isParentView(menu) {
  return menu.parentId !== 0 && menu.type === menuConst.TYPE_DIR
}

// 域名特殊字符替换
function innerLinkReplaceEach(url) {
  return url
    .replace('http://', '')
    .replace('https://', '')
    .replace('www.', '')
    .replaceAll('.', '/')
    .replaceAll(':', '/')
}

// 是否为http(s)://开头
function isHttp(link) {
  return link.indexOf('http://') === 0 || link.indexOf('https://') === 0
}

// 过滤菜单路由，
function filterChildren(childrenMap, lastRouter = false) {
  let children = []
  childrenMap.forEach(el => {
    if (el.children && el.children.length) {
      if (el.component === 'ParentView' && !lastRouter) {
        el.children.forEach(c => {
          c.path = el.path + '/' + c.path
          if (c.children && c.children.length) {
            children = children.concat(filterChildren(c.children, c))
            return
          }
          children.push(c)
        })
        return
      }
    }
    if (lastRouter) {
      el.path = lastRouter.path + '/' + el.path
      if (el.children && el.children.length) {
        children = children.concat(filterChildren(el.children, el))
        return
      }
    }
    children = children.concat(el)
  })
  return children
}

export const loadView = view => {
  let res
  for (const path in modules) {
    const dir = path.split('views/')[1].split('.vue')[0]
    if (dir === view) {
      res = () => modules[path]()
    }
  }
  return res
}
